﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;
using System.Net;
using System.Collections;
using System.Data.SQLite;
using System.IO;
using System.Security.Cryptography;

namespace Chatter.CoreServer
{
    /// <summary>
    /// Classe contenant les paramètres de configuration (serveur + serveur SMTP + base de données)
    /// </summary>
    public sealed class Config
    {
        private static Config _config;

        private ServerSettings _server;
        /// <summary>
        /// Accès à la structure 'ServerSettings'
        /// </summary>
        public ServerSettings server
        {
            get { return _server; }
        }

        private SMTPSettings _smtp;
        /// <summary>
        /// Accès à la structure 'SMTPSettings'
        /// </summary>
        public SMTPSettings smtp
        {
            get { return _smtp; }
        }

        private DbSettings _database;
        /// <summary>
        /// Accès à la structure 'DbSettings'
        /// </summary>
        public DbSettings database
        {
            get { return _database; } 
        }

        #region Private Attributes + Getters/Setters
    // PARAMETRES SERVER INFORMATION
        /// <summary>
        /// Structure de la configuration du serveur
        /// </summary>
        public struct ServerSettings
        {
            /// <summary>
            /// Paramètres de configuration du serveur
            /// </summary>
            /// <param name="settings"></param>
            public ServerSettings(Hashtable settings)
            {
                this._MOTD = settings["MOTD"].ToString();
                this._ip = IPAddress.Parse(settings["ip"].ToString());
                this._port = int.Parse(settings["port"].ToString());
                this._maxNbrUser = int.Parse(settings["maxNbrUser"].ToString());
                this._checkBansEvery = int.Parse(settings["checkBansEvery"].ToString()) * 1000; // En millisecondes
                this._startTrayMinimied = int.Parse(settings["startTrayMinimied"].ToString());
            }

            private string _MOTD;
            /// <summary>
            /// Message du jour
            /// </summary>
            public string MOTD
            {
                get { return _MOTD; }
            }

            private IPAddress _ip;
            /// <summary>
            /// Adresse IP du serveur
            /// </summary>
            public IPAddress ip
            {
                get { return _ip; }
            }

            private int _port;
            /// <summary>
            /// Port du serveur
            /// </summary>
            public int port
            {
                get { return _port; }
            }

            private int _maxNbrUser;
            /// <summary>
            /// Nombre maximal d'utilisateur
            /// </summary>
            public int maxNbrUser
            {
                get { return _maxNbrUser; }
            }

            private int _checkBansEvery;
            /// <summary>
            /// Vérification des bannissements toutes les x
            /// </summary>
            public int checkBansEvery
            {
                get { return _checkBansEvery; }
            }

            private int _startTrayMinimied;
            /// <summary>
            /// Minimiser le serveur au démarrage
            /// </summary>
            public int startTrayMinimied
            {
                get { return _startTrayMinimied; }
            }
        };

    // PARAMETRES SMTP INFORMATION
        /// <summary>
        /// Structure de la configuration du serveur SMTP
        /// </summary>
        public struct SMTPSettings
        {
            /// <summary>
            /// Paramètres de configuration du serveur SMTP
            /// </summary>
            /// <param name="settings"></param>
            public SMTPSettings(Hashtable settings)
            {
                this._emailAddress = settings["emailAddress"].ToString();
                this._password = settings["password"].ToString();
                this._smtpServer = settings["smtpServer"].ToString();
                this._smtpPort = int.Parse(settings["smtpPort"].ToString());
                this._enableSSL = bool.Parse(settings["enableSSL"].ToString());
            }

            private string _emailAddress;
            /// <summary>
            /// Adresse e-mail du serveur SMTP
            /// </summary>
            public string emailAddress
            {
                get { return _emailAddress; }
            }

            private string _password;
            /// <summary>
            /// Mot de passe du serveur SMTP
            /// </summary>
            public string password
            {
                get { return _password; }
            }

            private string _smtpServer;
            /// <summary>
            /// Adresse du serveur SMTP
            /// </summary>
            public string smtpServer
            {
                get { return _smtpServer; }
            }

            private int _smtpPort;
            /// <summary>
            /// Port du serveur SMTP
            /// </summary>
            public int smtpPort
            {
                get { return _smtpPort; }
            }

            private bool _enableSSL;
            /// <summary>
            /// Activation du protocole SSL
            /// </summary>
            public bool enableSSL
            {
                get { return _enableSSL; }                
            }
        };

    // PARAMETRES DATABASE INFORMATION
        /// <summary>
        /// Structure de la configuration pour la connexion à la base de données
        /// </summary>
        public struct DbSettings
        {
            /// <summary>
            /// Paramètres de configuration de la base de données
            /// </summary>
            /// <param name="settings"></param>
            public DbSettings(Hashtable settings)
            {
                this._dbFileName = settings["dbFileName"].ToString();
                this._newDb = bool.Parse(settings["newDb"].ToString());
                this._compressDb = bool.Parse(settings["compressDb"].ToString());
            }

            private string _dbFileName;
            /// <summary>
            /// Nom du fichier de la base de données
            /// </summary>
            public string dbFileName
            {
                get { return _dbFileName; }
            }

            private bool _newDb;
            /// <summary>
            /// Nouvelle base de données
            /// </summary>
            public bool newDb
            {
                get { return _newDb; }
            }

            private bool _compressDb;
            /// <summary>
            /// Base de données compressée
            /// </summary>
            public bool compressDb
            {
                get { return _compressDb; }
            }
        };
        #endregion

        /// <summary>
        /// Récupère la configuration avec un Singleton
        /// </summary>
        /// <returns>Instance de la classe Config</returns>
        public static Config GetConfig()
        {
            if (_config == null)
            {
                _config = new Config();
            }
            return _config;
        }

        private Config()
        {
            // INITIALISATION - SERVER INFORMATION
            this._server = new ServerSettings((Hashtable)ConfigurationManager.GetSection("ServerInformation"));

            // INITIALISATION - SMTP INFORMATION
            this._smtp = new SMTPSettings((Hashtable)ConfigurationManager.GetSection("SMTPInformation"));

            // INITIALISATION - DATABASE INFORMATION
            this._database = new DbSettings((Hashtable)ConfigurationManager.GetSection("DBInformation"));

            bool dbExists = File.Exists(this.database.dbFileName);

            Db.GetDB().connexion = new SQLiteConnection("Data Source=" + this.database.dbFileName + ";New=" + this.database.newDb + ";Compress=" + this.database.dbFileName + ";");

            if (!dbExists)
            {
                Db.GetDB().CreateBase();
            }
        }

        public string CalculateMD5Hash(string input)
        {
            // step 1, calculate MD5 hash from input
            MD5 md5 = System.Security.Cryptography.MD5.Create();
            byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes(input);
            byte[] hash = md5.ComputeHash(inputBytes);

            // step 2, convert byte array to hex string
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < hash.Length; i++)
            {
                sb.Append(hash[i].ToString("X2"));
            }
            return sb.ToString();
        }
    }
}
